import { BadgeAction, BadgeNode, BadgeView } from "./BadgeNode";
import { BadgeType } from "../../model/BadgeType";
import Timer from "../time/Timer";
import Singleton from "../context/Singleton";
import { Logger } from "../log/logger";
import Utils from "../utils/Utils";
import UIUtils from "../utils/UIUtils";

export default class BadgeManage extends Singleton {
    public static get I() { return this.Instance() }

    //红点刷新且状态改变时会广播此事件，参数 BadgeType
    public static UPDATE = "ON_BADGE_UPDAGE";

    private readonly interval = 1200;

    private readonly timeM = new Timer(this.loop, this, this.interval, true, true);

    /**节点池 */
    private _badges = new Map<BadgeType, BadgeNode>();

    /**节点组 */
    private _badgeGropu = new Map<BadgeType, BadgeType[]>();

    /**绑定节点UI */
    private _bindViews: BadgeView[] = [];

    /**脏节点池 */
    private _tempList = new Set<BadgeNode>();

    private _runing: boolean;

    onInit() {
        this.run();
    }

    /**开始执行红点逻辑 */
    run() {
        this.timeM.start();
        this._runing = true;
    }

    /**停止红点逻辑 */
    stop() {
        this.timeM.stop();
        this._runing = false;
        for (let elm of this._bindViews) {
            for (let view of elm.viewArr) {
                UIUtils.setBadge(view, false)
            }
        }
    }

    /**
     * 红点绑定UI
     * @param type 
     * @param view 绑定组件
     * @param caller 标识，方便统一移除
     * @param refresh 立即刷新
     */
    regist(type: BadgeType, view: Laya.Sprite, caller?: any, refresh: boolean = true) {

        let item = this.findBadgeView(type, caller);

        if (Utils.isNil(item)) {
            item = BadgeView.create();
            item.type = type;
            item.caller = caller || "defaultBadge";
            this._bindViews.push(item);
        }

        item.add(view);

        refresh && this.event(type);
    }


    /**
     * 移除绑定UI
     * @param view 
     * @param type 
     */
    unRegist(view: Laya.Sprite, type: BadgeType, caller: any) {
        Logger.logView(view, "解除绑定UI:")
        if (type != null) {
            let item = this.findBadgeView(type, caller);
            item && this._unRegist(item, view);
            return;
        }

        for (let item of this._bindViews) {
            let elm = item.find(view);
            if (Utils.isNil(elm)) continue;

            this.unRegist(view, item.type, caller);
        }
    }

    /**
     * 移除所有绑定
     * @param caller 标识
     */
    unRegistAll(caller: any) {
        for (let elm of this._bindViews) {

            if (elm.caller !== caller) continue;

            for (let view of elm.viewArr) {
                this._unRegist(elm, view)
            }
        }
    }

    /**
     * 添加节点监听
     * @param type 
     * @param action 
     * @returns 
     */
    add(type: BadgeType, param?: BadgeAction) {
        let elm = this.getOrAdd(type);
        elm.action = param != null ? param : null;
        return elm;
    }

    getOrAdd(type: BadgeType) {
        let elms = this._badges;
        if (elms.has(type)) {
            let elm = elms.get(type);
            return elm;
        }

        let elm = new BadgeNode();
        elm.key = type;
        elms.set(type, elm);
        return elm;
    }

    remove(type: BadgeType) {
        let elms = this._badges;
        if (!elms.has(type)) {
            return;
        }

        elms.delete(type);
    }

    addGropu(group: BadgeType, badges: BadgeType[], action?: BadgeAction) {

        this.add(group, action);

        this._badgeGropu.set(group, badges);
        for (let elm of badges) {
            let item = this.getOrAdd(elm);
            item.addGropu(group);
        }
    }

    getElm(tyep: BadgeType) {
        let badge = this._badges.get(tyep);
        return badge;
    }

    getValueByType(type: BadgeType) {
        let elm = this._badges.get(type);
        if (elm == null) {
            return 0;
        }

        if (!this._badgeGropu.has(type)) {
            return elm.value;
        }

        let values = this._badgeGropu.get(type), temp = 0;
        for (let k of values) {
            temp += this.getValueByType(k);
        }

        return elm.value + temp
    }

    /**刷新红点 */
    event(...keyLst: BadgeType[]) {

        if (!this._runing) return;

        for (let k of keyLst) {
            let elm = this.getElm(k);
            if (!elm) continue;

            this._tempList.add(elm);
        }
    }

    private loop() {
        let temLst = this._tempList;
        if (temLst.size <= 0) {
            return;
        }

        for (let elm of temLst) {
            elm.update();
            this.updateView(elm.key);
        }

        this._tempList.clear();
    }


    private findBadgeView(type: BadgeType, caller: any) {
        let arr = this._bindViews;
        if (arr.length === 0) {
            return null;
        }

        for (let elm of arr) {
            if (elm.type === type && elm.caller === caller) {
                return elm;
            }
        }
        return null;
    }

    private updateView(type: BadgeType) {

        for (let v of this._bindViews) {
            if (v.type === type) {
                v.badge = this.getValueByType(type) > 0;

                let elm = this.getElm(type);
                if (!elm || elm.groupSize <= 0) continue;

                for (let item of elm.groups) {
                    this.updateView(item)
                }
            }
        }


    }

    private _unRegist(item: BadgeView, view: Laya.Sprite) {
        item.remove(view);
        if (item.isEmpty()) {
            this._bindViews.remove(item)
            BadgeView.recover(item);
        }
    }

}